//
// Created by QU on 2024/1/16.
//

// c++ standard library
#include <cassert>
#include <iostream>
#include <list>
#include <vector>
#include <map>
#include <set>


// boost library
#include <boost/smart_ptr.hpp>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include <boost/smart_ptr/owner_less.hpp>
#include <boost/enable_shared_from_this.hpp>

// using namespace
using std::cin, std::cout, std::endl;
using boost::shared_ptr;
using boost::weak_ptr;
using boost::intrusive_ptr;

namespace counted {
    struct counted_data {
        int m_count = 0;
        // ......
    };

    void intrusive_ptr_add_ref(counted_data *p) {
        ++(p->m_count);
    }

    void intrusive_ptr_release(counted_data *p) {
        if (--(p->m_count) == 0) {
            delete p;
        }
    }
}

int main(int argc, char const * argv []){
    // intrusive_ptr   侵入_指针
    // intrusive_ptr也是一种引用计数型智能指针, 但是和scoped_ptr不一样, intrusive_ptr需要一些额外的代码才能使用他.

    // 如果现有的代码中已经包含了引用机制管理的对象, 那么intrusive_ptr是一个非常好的选择, 他可以包装现有对象来得到与shared_ptr类似的智能指针.
//    intrusive_ptr接口和shared_ptr很像, 支持比较操作, 强制类型转换: boost::static_pointer_cast<>() boost::dynamic_pointer_cast<>()
//    主要是intrusive_ptr本身不直接管理引用计数, 而是需要你自己实现两个管理计数相关的函数间接管理引用计数.
//    void intrusive_ptr_add_ref(T * p);
//    void intrusive_ptr_release(T * p);
//    由于ADL的原因, 我们需要在类所在的名称空间或者boost空间上实现这两个函数.

    // 其中intrusive_ptr的构造函数和reset()函数中和上面的管理引用计数的函数相比增加了一个bool类型的参数,
    // 这个参数add_ref==false, 那么就相当于weak_ptr, 只是简单的观察对象.

    // intrusive_ptr 的使用
    // 假如我们有一个自己实现引用计数的类或者结构体.(写在上面)

    typedef boost::intrusive_ptr<counted::counted_data> counted_ptr;
    counted_ptr p(new counted::counted_data);
    assert(p);
    assert(p->m_count == 1);

    counted_ptr p2(p);      // 指针拷贝函数构造
    assert(p->m_count == 2);    // 增加

    counted_ptr weak_p(p.get(), false);
    assert(weak_p->m_count == 2);       // 不增加

    p2.reset();
    assert(!p2);
    assert(p->m_count == 1);

    // 程序结束, 正常析构.

    // 为了进一步简化实现引用的计数工作, intrusive_ptr在<boost/smart_ptr/intrusive_ref_counter.hpp>中定义了一个辅助类
    // intrusive_ref_counter类.

    // intrusive_ref_counter类内部定义了一个计数器变量m_ref_counter, 并且使用模版已经配置好了实现引用计数的增减,
    // 默认的策略是线程安全的 thread_safe_counter.
    // intrusive_ref_counter需要被继承使用, 这样子类就会继承自动获得引用计数器的能力, 之前的需要实现两个具体函数的代码可以简化如下:

}
//    #include <boost/smart_ptr/intrusive_ref_counter.hpp>
//    namespace counted {
//        struct counted_data : boost::intrusive_ref_counter<counted_data> {      // 继承intrusive_ref_counter<TYPE>
//            // ......
//        };
//    }

